
/* octree						axis
* 
	/---------------            +Y
   /  5	  /	 6	   /|			|
  /------/------- /	|			|
 /	1	/	2	 /|6|			|       +Z
 |------|-------| |	|			|     /
 |	1	|	2	|2|/|			|    /
 |      |		| /	|			|   /
 |------|-------|/|8|			|  /
 |		|		| |	|			| /
 |	3	|	4	|4|/			|/
 |______|_______|/				------------ +X
								
					
*/


/* block
	   4--------5		 *---4----*
	  /|       /|		/|		 /|
	 / |      /	|	   7 |		5 |
	/  |     /	|	  /  8	   /  9
   7--------6	|	 *----6---*   |
   |   |    |	|	 |   |	  |   |
   |   0----|---1	 |	 *---0|---*
   |  /     |  /	 11	/	  10 /
   | /      | /		 | 3	  | 1
   |/       |/		 |/       |/
   3--------2		 *---2----*
*/

#pragma once
#include <vector>
#include <math.h>
#include "Mesh.h"
#include "Vector.h"
#include "Mesh.h"
#include "SurfaceNets.h"
#include "LookkupTable.h"

#include <math.h>
#define MaxDepthLevel 0  

namespace mini
{
	class CVoxelBrush;
	static CPoint3F c(rand() % 255 / 255.0f, rand() % 255 / 255.0f, rand() % 255 / 255.0f);

	class CBlockNode
	{
	public:
		CBlockNode();
		virtual ~CBlockNode();
		void setSize(CPoint3F min, CPoint3F max, CPoint3F color = c);
		void buildVoxel();
		void buildVoxelMesh(const CVector& pos);

		void buildMesh(bool bBuildMesh, const CVector& pos);

		void setPosition(const CVector& pos);
		void check(CVoxelBrush* pBoundBox, bool bIncrease);
		void test();
		void calculateFaceBlock(std::vector< std::vector< std::vector<CBlockNode*>>>& blocks);
		void marchingCube(CBoundBox& boundBox);
		void buildMeshEx();

	private:
		void buildchildBlockOne();
		void buildchildBlockTwo();
		void buildchildBlockThree();
		void buildchildBlockFour();
		void buildchildBlockFive();
		void buildchildBlockSix();
		void buildchildBlockSeven();
		void buildchildBlockEight();

		void marchingCubeFront(CBoundBox& boundBox);
		void marchingCubeBack(CBoundBox& boundBox);
		void marchingCubeLeft(CBoundBox& boundBox);
		void marchingCubeRight(CBoundBox& boundBox);
		void marchingCubeTop(CBoundBox& boundBox);
		void marchingCubeBottom(CBoundBox& boundBox);

	public:
		int mCubeIndex = 0;
		//octree
		CBlockNode* mpParent = nullptr;
		std::vector<CBlockNode*> mChildren;
		CPoint3F mMin;
		CPoint3F mMax;
		CPoint3F mCenter;
		CBoundBox* mpBound = nullptr;
		std::vector<VertexFormatVC>	mVerticesOriginal;
		std::vector<VertexFormatVC>	mVertices;
	//	std::vector<UINT32>		mVerticesShow;
		std::vector<UINT32>		mIndices;

		//0 front 1 back 2 left 3 right 4 top 5 bottom
		std::vector<CPoint4I>	mPlane;

		int mDepthLevel = 0;
		CActor* mpActor = nullptr;
		int		mOctreeChildIndex = -1;
		bool mbProcess = false;

	};

	class CTerrainBlock
	{
	public:
		CTerrainBlock();
		~CTerrainBlock();
		CMeshUnit* convertToMesh();
		void buildVoxelMesh(const CVector& pos);
		void setPosition(const CVector& pos);
		void showVoxel(bool bvalue);
		bool isShowVoxel();
		void setSize(CPoint3F min, CPoint3F max, CPoint3F color = c);
		void buildVoxel();
		void check(CVoxelBrush* pBrush, bool bIncrease);
		void test();
		void testOne();
		void setDepthLevel(int nLevel);
		void calculateFaceBlock();

	public:
		CBoundBox mBound;
		static int const SBlockHalfSize = 1;
		CActor* mpActor = nullptr;

	private:
		void marchingCube();
		void convertMeshFinished();

		void checkYZPlane(int nLength);

		void checkXZPlane(int nLength);

		void checkXYPlane(int nLength);

		void convertMeshEx();
		void convertMesh();
		void convertSidePlane();
		void convertFrontPlane();
		void convertBackPlane();
		void convertLeftPlane();
		void convertRightPlane();
		void convertTopPlane();
		void convertBottomPlane();

	private:
		int mLength = 0;
		std::vector<VertexFormatVC>	mVertices;
		std::vector<UINT32>		mIndices;
		bool mbShowVoxel = false;
		CBlockNode mBlockNode;
		CSurfaceNets	mSurfaceNet;
		CMeshUnit* mpMeshUnit = nullptr;
		std::vector< std::vector< std::vector<CBlockNode*>>>mVoxelBlock;
	};
}